package cn.akwangl.common.utils;

import org.springframework.data.redis.core.RedisTemplate;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * Redis 工具类.
 *
 * @author youyongkun
 * @date 2022/4/11 14:49
 * @since 0.0.5
 */
public class RedisUtils {

    private RedisTemplate<String, Object> redisTemplate;

    public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    /**
     * 指定key存入Redis.
     *
     * @param key redis key
     * @param obj Java Object
     * @author youyongkun
     * @date 2022/4/11 15:03
     */
    public void putObj(String key, Object obj) {
        redisTemplate.opsForValue().set(key, obj);
    }

    /**
     * 获取指定key,Java 对象.
     *
     * @param key redis key
     * @return Java Object
     * @author youyongkun
     * @date 2022/4/11 15:02
     */
    public <T> T getObj(String key) {
        return (T) redisTemplate.opsForValue().get(key);
    }

    /**
     * 给定key是否存在.
     *
     * @param key redis key
     * @return true:存在 false:不存在
     * @author youyongkun
     * @date 2022/4/11 15:08
     */
    public boolean hasKey(String key) {
        return redisTemplate.hasKey(key);
    }

    /**
     * 获取{@code key}的生存时间(以秒为单位)。
     *
     * @param key redis key
     * @return 以秒为单位,-1 则为永久
     * @author youyongkun
     * @date 2022/4/11 15:10
     */
    public Long getExpire(String key) {
        return redisTemplate.getExpire(key);
    }

    /**
     * 将给定键的过期时间设置为日期戳.
     *
     * @param key  redis key
     * @param date 过期时间
     * @return true:成功 false:失败
     * @author youyongkun
     * @date 2022/4/11 15:14
     */
    public Boolean expireAt(String key, Date date) {
        return redisTemplate.expireAt(key, date);
    }

    /**
     * 设置过期时间
     *
     * @param key     redis key
     * @param timeout 过期时间
     * @param unit    时间单位
     * @return true:成功 false:失败
     * @author youyongkun
     * @date 2022/4/11 15:19
     */
    public Boolean expire(String key, long timeout, TimeUnit unit) {
        return redisTemplate.expire(key, timeout, unit);
    }

    /**
     * 修改 key 的名称.
     *
     * @param oldKey redis旧 key
     * @param newKey redis新 key
     * @author youyongkun
     * @date 2022/4/11 15:23
     */
    public void rename(String oldKey, String newKey) {
        redisTemplate.rename(oldKey, newKey);
    }

    /**
     * 将值 value 关联到 key ，并将 key 的过期时间设为 timeout
     *
     * @param key     redis key
     * @param value   java Object
     * @param timeout 过期时间
     * @param unit    时间单位, 天:TimeUnit.DAYS 小时:TimeUnit.HOURS 分钟:TimeUnit.MINUTES 秒:TimeUnit.SECONDS 毫秒:TimeUnit.MILLISECONDS
     * @author youyongkun
     * @date 2022/4/11 15:23
     */
    public void setEx(String key, Object value, long timeout, TimeUnit unit) {
        redisTemplate.opsForValue().set(key, value, timeout, unit);
    }

    /**
     * 只有在 key 不存在时设置 key 的值
     *
     * @param key   redis key
     * @param value java Object
     * @return 之前已经存在返回false, 不存在返回true
     * @author youyongkun
     * @date 2022/4/11 15:23
     */
    public boolean setIfAbsent(String key, Object value) {
        return redisTemplate.opsForValue().setIfAbsent(key, value);
    }

    //********************************************************** 批量操作 ********************************************************

    /**
     * 获取指定前缀key.
     *
     * @param prefixKey Redis 前缀key
     * @return 返回key集合
     * @author youyongkun
     * @date 2022/4/11 16:05
     */
    public Set<String> keys(String prefixKey) {
        return redisTemplate.keys(prefixKey);
    }

    /**
     * 批量获取数据.
     *
     * @param keys redis key
     * @return 同一类Java 对象.
     * @author youyongkun
     * @date 2022/4/11 16:10
     */
    public <T> List<T> multiGet(Collection<String> keys) {
        return (List<T>) redisTemplate.opsForValue().multiGet(keys);
    }

    /**
     * 批量设置 Redis 值.
     *
     * @param map k,v
     * @author youyongkun
     * @date 2022/4/11 16:12
     */
    public <T> void multiSet(Map<String, T> map) {
        redisTemplate.opsForValue().multiSet(map);
    }

    /**
     * 删除key
     *
     * @param key redis key
     * @return true:成功 false:失败
     * @author youyongkun
     * @date 2022/4/11 15:20
     */
    public Boolean delete(String key) {
        return redisTemplate.delete(key);
    }

    /**
     * 批量删除key
     *
     * @param keys redis key集合
     * @return 被删除的数量
     * @author youyongkun
     * @date 2022/4/11 15:21
     */
    public Long delete(Collection<String> keys) {
        return redisTemplate.delete(keys);
    }
}
